Find/Replace with formatting

I'm working with DOORS 8.2, and I see that the find/replace does not incorporate formatting.

I've been trying to put together a dxl script to find all occurrences of "shall" in the object text and bold them.
It seems like it should be easy to do, but I need guidance.

Does anyone have something like this already typed up? Thanks!
meldobbs - Fri Sep 17 15:14:55 EDT 2010

Re: Find/Replace with formatting
SystemAdmin - Fri Sep 17 15:32:24 EDT 2010

But why? Do you want to present that each object text with shall is a real requirement? Why not have an attribute "Requirement?" that this object is a real requirement?

Re: Find/Replace with formatting
meldobbs - Mon Sep 20 09:35:37 EDT 2010

SystemAdmin - Fri Sep 17 15:32:24 EDT 2010
But why? Do you want to present that each object text with shall is a real requirement? Why not have an attribute "Requirement?" that this object is a real requirement?

Appreciate the suggestion, but I do already have a "Requirement" attribute that identifies statements containing "shall" or "should".

It has become a helpful convention here to bold the words "shall" and "should" in the text, but apparently they were not bolded in the source document we imported. This seems like a pretty straightforward thing to do, but I'm still a novice.

Re: Find/Replace with formatting
meldobbs - Mon Sep 20 12:14:07 EDT 2010

I was hoping something like this would work:
Module m = current
Object o

string bodyText
string shall = "shall"
string should = "should"
string boldShall = "{\\b shall}"
string boldShould = "{\\b should}"
int offset
int len

for o in m do
{
bodyText = o."Object Text"
print bodyText "\n"

if (findRichText(bodyText, should, offset, len, false))
{
bodyText = replaceRichText(bodyText, offset, len, boldShould)
}
if (findRichText(bodyText, shall, offset, len, false))
{
bodyText = replaceRichText(bodyText, offset, len, boldShall)
}

o."Object Text" = bodyText
}

But I'm clearly not manipulating the rich text correctly...
Before:
This shall be my example.

After:
This \{\\b shall\} be my example.

How can I keep those extra escape characters from being inserted?

Re: Find/Replace with formatting
Mathias Mamsch - Tue Sep 21 03:13:47 EDT 2010

meldobbs - Mon Sep 20 12:14:07 EDT 2010
I was hoping something like this would work:
Module m = current
Object o

string bodyText
string shall = "shall"
string should = "should"
string boldShall = "{\\b shall}"
string boldShould = "{\\b should}"
int offset
int len

for o in m do
{
bodyText = o."Object Text"
print bodyText "\n"

if (findRichText(bodyText, should, offset, len, false))
{
bodyText = replaceRichText(bodyText, offset, len, boldShould)
}
if (findRichText(bodyText, shall, offset, len, false))
{
bodyText = replaceRichText(bodyText, offset, len, boldShall)
}

o."Object Text" = bodyText
}

But I'm clearly not manipulating the rich text correctly...
Before:
This shall be my example.

After:
This \{\\b shall\} be my example.

How can I keep those extra escape characters from being inserted?

I think replaceRichText will retain the formatting therefore escaping all richtext markup in your string, therefore you cannot use that. What you could do is something like this:
 

Module m = current
Object o = current
 
// set the object text to something that already contains richText so we are sure we retain formatting
o."Object Text" = richText "We sh{\\b a}ll da{\\b nc}e!"
 
// read the richText 
Buffer bodyText = create() 
bodyText = richTextWithOle o."Object Text"
 
Buffer newText = create()
 
int len, offset
if (findRichText(tempStringOf bodyText, "shall", offset, len, false) && offset > 0)
{
   // manually replace the richText
   combine (newText, bodyText, 0, offset-1)  
   newText += "{\\b shall}" 
   combine (newText, bodyText, offset+len) 
}
 
o."Object Text" = richText tempStringOf newText
 
delete newText
delete bodyText

 


Hope that helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Re: Find/Replace with formatting
meldobbs - Wed Sep 29 10:27:38 EDT 2010

Mathias Mamsch - Tue Sep 21 03:13:47 EDT 2010

I think replaceRichText will retain the formatting therefore escaping all richtext markup in your string, therefore you cannot use that. What you could do is something like this:
 

Module m = current
Object o = current
 
// set the object text to something that already contains richText so we are sure we retain formatting
o."Object Text" = richText "We sh{\\b a}ll da{\\b nc}e!"
 
// read the richText 
Buffer bodyText = create() 
bodyText = richTextWithOle o."Object Text"
 
Buffer newText = create()
 
int len, offset
if (findRichText(tempStringOf bodyText, "shall", offset, len, false) && offset > 0)
{
   // manually replace the richText
   combine (newText, bodyText, 0, offset-1)  
   newText += "{\\b shall}" 
   combine (newText, bodyText, offset+len) 
}
 
o."Object Text" = richText tempStringOf newText
 
delete newText
delete bodyText

 


Hope that helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Mathias,
Thanks so much for the help. I modified your code a bit to allow for looping through the entire module and to catch instances of multiple shalls in a single object. Here's what I ended up with:
Module m = current
Object o

Buffer bodyText = create()
Buffer newText = create()

int len, offset

for o in m do
{
newText = ""
bodyText = richTextWithOle o."Object Text"
while (findRichText(tempStringOf bodyText, "shall", offset, len, false) && offset > 0)
{
combine (newText, bodyText, 0, offset-1)
newText += "{\\b shall}"
//combine (newText, bodyText, offset+len)
bodyText = bodyTextoffset+len:
}
combine (newText, bodyText, 0)
o."Object Text" = richText tempStringOf newText
}

delete newText
delete bodyText

Seems to work like a charm. Thanks again!

Re: Find/Replace with formatting
meldobbs - Wed Sep 29 10:34:22 EDT 2010

meldobbs - Wed Sep 29 10:27:38 EDT 2010
Mathias,
Thanks so much for the help. I modified your code a bit to allow for looping through the entire module and to catch instances of multiple shalls in a single object. Here's what I ended up with:
Module m = current
Object o

Buffer bodyText = create()
Buffer newText = create()

int len, offset

for o in m do
{
newText = ""
bodyText = richTextWithOle o."Object Text"
while (findRichText(tempStringOf bodyText, "shall", offset, len, false) && offset > 0)
{
combine (newText, bodyText, 0, offset-1)
newText += "{\\b shall}"
//combine (newText, bodyText, offset+len)
bodyText = bodyTextoffset+len:
}
combine (newText, bodyText, 0)
o."Object Text" = richText tempStringOf newText
}

delete newText
delete bodyText

Seems to work like a charm. Thanks again!

Here it is again with proper formatting ...
 

Module m = current
Object o
 
Buffer bodyText = create()
Buffer newText = create()
 
int len, offset
 
for o in m do
{
   newText = ""
   bodyText = richTextWithOle o."Object Text"
   while (findRichText(tempStringOf bodyText, "shall", offset, len, false) && offset > 0)
   {
      combine (newText, bodyText, 0, offset-1)
      newText += "{\\b shall}"
      //combine (newText, bodyText, offset+len)
      bodyText = bodyText[offset+len:]
   }
   combine (newText, bodyText, 0)
   o."Object Text" = richText tempStringOf newText
}
 
delete newText
delete bodyText

Re: Find/Replace with formatting
llandale - Wed Sep 29 11:51:41 EDT 2010

meldobbs - Wed Sep 29 10:34:22 EDT 2010

Here it is again with proper formatting ...
 

Module m = current
Object o
 
Buffer bodyText = create()
Buffer newText = create()
 
int len, offset
 
for o in m do
{
   newText = ""
   bodyText = richTextWithOle o."Object Text"
   while (findRichText(tempStringOf bodyText, "shall", offset, len, false) && offset > 0)
   {
      combine (newText, bodyText, 0, offset-1)
      newText += "{\\b shall}"
      //combine (newText, bodyText, offset+len)
      bodyText = bodyText[offset+len:]
   }
   combine (newText, bodyText, 0)
   o."Object Text" = richText tempStringOf newText
}
 
delete newText
delete bodyText

Try your code with these texts

Text                                    Bold?           Result
The pond is too shallow.                Yes     The pond is too SHALLow.
The system Shall do stuff.              No      The system Shall do stuff.
The system shall do shallshall stuff.   2 of 3  The system SHALL do SHALLshall stuff.
shall do it.                            No      shall do it.


Not sure your while statement needs "&& offset > 0", but if it does I think it should be "&& offset >= 0". In any event, only 'combine' if (offset>0).

You may need to extract the raw text of the object and search for 'shall' or 'Shall', and if found then validate its surrounded with white space or punctuation. When its found search the rich text and if valid then use it (combine, newtext, and bodytext); if invalid then just do the combine and update bodyText with [offset:]. Yuuuuck.

I get the feeling there are other cases I didn't think of.

Searching the raw text will improve effeciency when there is an OLE diagram which makes the text a million bytes. Also, you can set the attr quickly o."Object Text" = richText newText which I suspect is faster than converting it to a string with tempStringOf, then setting that. that works because 'richText(Buffer)' may return a string but it also returns a pointer to the buffer when assigning to a variable.

 

 

  • Louie

 

 

Re: Find/Replace with formatting
Mathias Mamsch - Wed Sep 29 12:47:46 EDT 2010

llandale - Wed Sep 29 11:51:41 EDT 2010

Try your code with these texts

Text                                    Bold?           Result
The pond is too shallow.                Yes     The pond is too SHALLow.
The system Shall do stuff.              No      The system Shall do stuff.
The system shall do shallshall stuff.   2 of 3  The system SHALL do SHALLshall stuff.
shall do it.                            No      shall do it.


Not sure your while statement needs "&& offset > 0", but if it does I think it should be "&& offset >= 0". In any event, only 'combine' if (offset>0).

You may need to extract the raw text of the object and search for 'shall' or 'Shall', and if found then validate its surrounded with white space or punctuation. When its found search the rich text and if valid then use it (combine, newtext, and bodytext); if invalid then just do the combine and update bodyText with [offset:]. Yuuuuck.

I get the feeling there are other cases I didn't think of.

Searching the raw text will improve effeciency when there is an OLE diagram which makes the text a million bytes. Also, you can set the attr quickly o."Object Text" = richText newText which I suspect is faster than converting it to a string with tempStringOf, then setting that. that works because 'richText(Buffer)' may return a string but it also returns a pointer to the buffer when assigning to a variable.

 

 

  • Louie

 

 

@Louie: You are right, this is indeed more complicated. What I did not get is that findRichText did not catch the uppercase/lowercase stuff, since the 'matchcase' bool parameter is set to false. In my tests this works fine.

@meldobbs: Ouch what a bad memory leak!

...
bodyText = bodyText[offset+len:] // never do this with a buffer, when you manipulate large strings!! 
 
// Since buffer[x:y] can also a buffer OR a string you may just throw away the old buffer
// without deleting it and assign a (newly created) buffer that contains the range of the old buffer. 
// Always do like this: 
// 
// Buffer temp = create(); combine(temp, bodyText, offset+len); 
// delete bodyText; bodyText = temp 
//

 


You probably need to scan the RTF string after the occurence of the "shall" for non RTF markup characters. An RTF keyword always starts with \keyword and ends with a space. In addition you need to take into account braces { } which terminate keywords and the backslash itself (which indicates a probable start of another keyword. You should not bold the shall if you have a non-space after the shall.

Regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Re: Find/Replace with formatting
DOORS_USER - Mon Oct 11 17:47:28 EDT 2010

meldobbs - Wed Sep 29 10:34:22 EDT 2010

Here it is again with proper formatting ...
 

Module m = current
Object o
 
Buffer bodyText = create()
Buffer newText = create()
 
int len, offset
 
for o in m do
{
   newText = ""
   bodyText = richTextWithOle o."Object Text"
   while (findRichText(tempStringOf bodyText, "shall", offset, len, false) && offset > 0)
   {
      combine (newText, bodyText, 0, offset-1)
      newText += "{\\b shall}"
      //combine (newText, bodyText, offset+len)
      bodyText = bodyText[offset+len:]
   }
   combine (newText, bodyText, 0)
   o."Object Text" = richText tempStringOf newText
}
 
delete newText
delete bodyText

I've been looking for code to do this. Thanks a ton for posting this. However, I ran the code as posted and found that if Object Text has several sentences (delimited by periods). Running the script multiple times would strip all the other sentences and leaving it with just one sentence.

Thanks!